#include "HalGPIO.h"
//#include "stm32f4xx_hal_gpio.h"

#define IO_NUM_MAX 0x5f

static GPIO_TypeDef *ioToPort(uint8_t io)
{
    int n = io >> 4;

    switch(n)
    {
    case 0x0:
        return GPIOA;

    case 0x1:
        return GPIOB;

    case 0x2:
        return GPIOC;

    case 0x3:
        return GPIOD;

    case 0x4:
        return GPIOE;

    case 0x5:
        return GPIOF;

    default:
        return GPIOG;
    }
}

static uint16_t ioToPin(uint8_t io)
{
    int n = io & 0xf;
    return (1 << n);
}

void HalGPIOSetLevel(uint8_t io, uint8_t level)
{
    if(io != HAL_GPIO_INVALID_IO)
    {
        HAL_GPIO_WritePin(ioToPort(io), ioToPin(io), (GPIO_PinState)(level != 0));
    }
}

uint8_t HalGPIOGetLevel(uint8_t io)
{
    if(io != HAL_GPIO_INVALID_IO)
    {
        return (uint8_t)HAL_GPIO_ReadPin(ioToPort(io), ioToPin(io));
    }
    return 0;   
}

void HalGPIOConfig(uint8_t io, HalGPIODirect_t dir)
{
    GPIO_InitTypeDef ioInit;

    if(io != HAL_GPIO_INVALID_IO)
    {
        ioInit.Pin  = ioToPin(io); 
        ioInit.Mode = (dir == HAL_IO_OUTPUT ? GPIO_MODE_OUTPUT_PP : GPIO_MODE_INPUT);
        ioInit.Pull = GPIO_PULLUP;
        ioInit.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        
        HAL_GPIO_Init(ioToPort(io), &ioInit);
    }
}

void HalGPIOPortSetLevel(uint8_t port, uint16_t level)
{
    GPIO_TypeDef *GPIOx = ioToPort(port);

    GPIOx->ODR = level;
}

uint16_t HalGPIOPortGetLevel(uint8_t port)
{
    GPIO_TypeDef *GPIOx = ioToPort(port);
    
    return (uint16_t)GPIOx->IDR;
}

void HalGPIOPortConfig(uint8_t port, HalGPIODirect_t dir)
{
    GPIO_InitTypeDef ioInit;
    ioInit.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4 \
                |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9 \
                |GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 \
                |GPIO_PIN_15;
    ioInit.Mode = (dir == HAL_IO_OUTPUT ? GPIO_MODE_OUTPUT_PP : GPIO_MODE_INPUT);   
    ioInit.Pull = GPIO_PULLUP;
    ioInit.Speed = GPIO_SPEED_FREQ_VERY_HIGH;    
    HAL_GPIO_Init(ioToPort(port), &ioInit);     
}

void HalGPIOInitialize(void)
{
}


